// ----------------------------------------------------------
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v.2.0. If a copy of the MPL
// was not distributed with this file, You can obtain one
// at http://mozilla.org/MPL/2.0/.
// ----------------------------------------------------------
// Codebase: https://github.com/ArKuznetsov/cpdb/
// ----------------------------------------------------------

#Использовать 1commands
#Использовать fs

Перем Лог;           // - Объект    - объект записи лога приложения
Перем Сервер;        // - Строка    - адрес сервера СУБД
Перем Пользователь;  // - Строка    - Пользователь сервера СУБД
Перем Пароль;        // - Строка    - Пароль пользователя сервера СУБД

#Область ПрограммныйИнтерфейс

// Функция, возвращает адрес сервера СУБД
//
// Возвращаемое значение:
//   Строка    - адрес сервера СУБД
//
Функция Сервер() Экспорт

	Возврат Сервер;

КонецФункции // Сервер()

// Процедура, устанавливает адрес сервера СУБД
//
// Параметры:
//   НовоеЗначение    - Строка    - новый адрес сервера СУБД
//
Процедура УстановитьСервер(Знач НовоеЗначение) Экспорт

	Сервер = НовоеЗначение;

КонецПроцедуры // УстановитьСервер()

// Функция, возвращает пользователя сервера СУБД
//
// Возвращаемое значение:
//   Строка    - пользователь сервера СУБД
//
Функция Пользователь() Экспорт

	Возврат Пользователь;

КонецФункции // Пользователь()

// Процедура, устанавливает пользователя сервера СУБД
//
// Параметры:
//   НовоеЗначение    - Строка    - новый пользователь сервера СУБД
//
Процедура УстановитьПользователь(Знач НовоеЗначение) Экспорт

	Пользователь = НовоеЗначение;

КонецПроцедуры // УстановитьПользователь()

// Процедура, устанавливает пароль пользователя сервера СУБД
//
// Параметры:
//   НовоеЗначение    - Строка    - новый пароль пользователь сервера СУБД
//
Процедура УстановитьПароль(Знач НовоеЗначение) Экспорт

	Пароль = НовоеЗначение;

КонецПроцедуры // УстановитьПароль()

// Функция проверяет существование базы на сервере СУБД
//
// Параметры:
//   База                              - Строка    - имя базы данных
//   ВариантСообщенияОСуществовании    - Строка    - в каких случаях выводить сообщение о существании БД
//
// Возвращаемое значение:
//   Булево    - Истина - база существует на сервере СУБД
//
Функция БазаСуществует(База, ВариантСообщенияОСуществовании = Неопределено) Экспорт

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         |SELECT
	                         |	COUNT(name)
	                         |FROM
	                         |	sysdatabases
	                         |WHERE
	                         |	name = '%1';
	                         |
	                         |SET NOCOUNT OFF"" ",
	                         База);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если КодВозврата = 0 Тогда
		РезультатЗапроса = СокрЛП(СтрЗаменить(РезультатЗапроса, "-", ""));
		Результат = РезультатЗапроса = "1";
	Иначе
		ТекстОшибки = СтрШаблон("Ошибка проверки существования базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	ВариантыСообщения = ВариантыСообщенияОСуществованииБД();

	Если НЕ ЗначениеЗаполнено(ВариантСообщенияОСуществовании) Тогда
		ВариантСообщенияОСуществовании = ВариантыСообщения.НеСообщать;
	КонецЕсли;

	ШаблонБазаСуществует = "База ""%1"" уже существует!";
	ШаблонБазаНеСуществует = "База ""%1"" не существует!";

	Если ВариантСообщенияОСуществовании = ВариантыСообщения.СообщатьОСуществовании
	   И Результат Тогда
		Лог.Предупреждение(ШаблонБазаСуществует, База);
	ИначеЕсли ВариантСообщенияОСуществовании = ВариантыСообщения.СообщатьОбОтсутствии
	        И НЕ Результат Тогда
		Лог.Предупреждение(ШаблонБазаНеСуществует, База);
	ИначеЕсли ВариантСообщенияОСуществовании = ВариантыСообщения.ИсключениеПриСуществовании
	        И Результат Тогда
		ВызватьИсключение СтрШаблон(ШаблонБазаСуществует, База);
	ИначеЕсли ВариантСообщенияОСуществовании = ВариантыСообщения.ИсключениеПриОтсутствии
	        И НЕ Результат Тогда
		ВызватьИсключение СтрШаблон(ШаблонБазаНеСуществует, База);
	ИначеЕсли Результат Тогда
		Лог.Отладка(ШаблонБазаСуществует, База);
	Иначе
		Лог.Отладка(ШаблонБазаНеСуществует, База);
	КонецЕсли;

	Возврат Результат;

КонецФункции // БазаСуществует()

// Функция получает список баз с сервера СУБД
//
// Параметры:
//   ФильтрБазПоИмени    - Строка    - фильтр имен баз в формате для оператора "LIKE"
//   ФильтрПоТаблице     - Строка    - фильтр по наличию в базе данных таблицы с указанным именем
//   ВключаяСистемные    - Булево    - Истина - в результат будут включены системные базы данных
//                                     (master, model, tempdb, msdb)
//
// Возвращаемое значение:
//   Соответствие Из Структура           - список баз на сервере СУБД
//     * Имя                   - Строка    - имя базы данных
//     * Ид                    - Число     - идентификатор базы данных
//     * ИдСоздателя           - Число     - идентификатор пользователя, создавшего базу
//     * Статус1               - Число     - флаги состояния базы данных
//     * Статус2               - Число     - флаги состояния базы данных
//     * ДатаСоздания          - Строка    - дата создания базы данных
//     * РежимСовместимости    - Число     - версия режима совместимости базы
//     * ФайлДанных            - Строка    - путь к файлу данных
//
Функция СписокБаз(ФильтрБазПоИмени = "", ФильтрПоТаблице = "", ВключаяСистемные = Ложь) Экспорт

	Условие = "";
	Если ЗначениеЗаполнено(ФильтрБазПоИмени) Тогда
		Условие = СтрШаблон("WHERE DB.name LIKE '%1'", ФильтрБазПоИмени);
	КонецЕсли;

	Если НЕ ВключаяСистемные Тогда
		Ограничение = "DB.name NOT IN ('master', 'model', 'tempdb', 'msdb')";
		Если ЗначениеЗаполнено(Условие) Тогда
			Условие = СтрШаблон("%1 AND %2", Условие, Ограничение);
		Иначе
			Условие = СтрШаблон("WHERE %1", Ограничение);
		КонецЕсли;
	КонецЕсли;

	ТекстФильтрПодготовка = "";
	ТекстФильтрСоединение = "";
	ТекстФильтрУдаление = "";
	
	Если ЗначениеЗаполнено(ФильтрПоТаблице) Тогда
		ТекстФильтрПодготовка =
			СтрШаблон("CREATE TABLE #FilteredBases (name NVARCHAR(50));
		              |EXEC sp_MSforeachdb
		              |'INSERT INTO #FilteredBases
		              |SELECT
		              |''?'' AS name
		              |FROM ?.sys.objects
		              |WHERE
		              |type = ''U'' AND name = ''%1'''",
		              ФильтрПоТаблице);
		ТекстФильтрСоединение = "INNER JOIN #FilteredBases AS FilteredBases
		                        |ON DB.name = FilteredBases.name";
		ТекстФильтрУдаление = "DROP TABLE #FilteredBases";
	КонецЕсли;

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         |%1
	                         |SELECT
	                         |	DB.name AS name,
	                         |	DB.dbid AS dbid,
	                         |	DB.sid AS sid,
	                         |	DB.status AS status1,
	                         |	DB.status2 AS status2,
	                         |	DB.crdate AS crdate,
	                         |	DB.cmptlevel AS cmptlevel,
	                         |	DB.filename AS filename
	                         |FROM
	                         |	sysdatabases AS DB
	                         |%2
	                         |%4
	                         |%3;
	                         |SET NOCOUNT OFF"" ",
	                         ТекстФильтрПодготовка,
	                         ТекстФильтрСоединение,
	                         ТекстФильтрУдаление,
	                         Условие);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса, "|", Истина);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения списка баз на сервере ""%1"":%2%3",
		                        Сервер,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Разделитель = "---";
	Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
	Если Поз > 0 Тогда
		РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
	КонецЕсли;

	ПоляОписания = "Имя
	               |Ид
	               |ИдСоздателя
	               |Статус1
	               |Статус2
	               |ДатаСоздания
	               |РежимСовместимости
	               |ФайлДанных";
	ПоляОписания = СтрРазделить(ПоляОписания, Символы.ПС, Ложь);

	СписокБаз = Новый Соответствие();
	
	Текст = Новый ТекстовыйДокумент();
	Текст.УстановитьТекст(РезультатЗапроса);
	
	Для й = 1 По Текст.КоличествоСтрок() Цикл

		СтрокаРезультатаЗапроса = Текст.ПолучитьСтроку(й);
		Если НЕ ЗначениеЗаполнено(СтрокаРезультатаЗапроса) Тогда
			Продолжить;
		КонецЕсли;

		ОписаниеБазы = СтрокаРезультатаЗапросаВСтруктуру(СтрокаРезультатаЗапроса, ПоляОписания);

		Для Каждого ТекЭлемент Из ОписаниеБазы Цикл
			Если ТекЭлемент.Ключ = "ДатаСоздания" Тогда
				ОписаниеБазы[ТекЭлемент.Ключ] = ДатаИзСтроки(ТекЭлемент.Значение);
			КонецЕсли;
		КонецЦикла;

		СписокБаз.Вставить(ОписаниеБазы.Имя, ОписаниеБазы);

	КонецЦикла;

	Возврат СписокБаз;

КонецФункции // СписокБаз()

// Функция проверяет существование таблицы в базе на сервере СУБД
//
// Параметры:
//   База       - Строка    - имя базы данных
//   Таблица    - Строка    - имя таблицы базы данных
//
// Возвращаемое значение:
//   Булево    - Истина - таблица существует в базе данных
//
Функция ТаблицаСуществует(База, Таблица) Экспорт

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         |SELECT
	                         |	COUNT(name)
	                         |FROM
	                         |	%1.sys.objects
	                         |WHERE
	                         |	type = 'U'
	                         |	AND name = '%2';
	                         |
	                         |SET NOCOUNT OFF"" ",
	                         База,
	                         Таблица);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если КодВозврата = 0 Тогда
		РезультатЗапроса = СокрЛП(СтрЗаменить(РезультатЗапроса, "-", ""));
		Результат = РезультатЗапроса = "1";
	Иначе
		ТекстОшибки = СтрШаблон("Ошибка проверки существования таблицы ""%1"" базы ""%2"": %3%4",
		                        База,
		                        Таблица,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Возврат Результат;

КонецФункции // ТаблицаСуществует()

// Процедура выполняет команду создания базы на сервере СУБД
//
// Параметры:
//   База                    - Строка    - имя базы данных
//   МодельВосстановления    - Строка    - новая модель восстановления (FULL, SIMPLE, BULK_LOGGED)
//   ПутьККаталогу           - Строка    - путь к каталогу для размещения файлов базы данных
//                                         если не указан, то файлы размещаются в каталоге по умолчанию SQL Server
//   ОшибкаЕслиСуществует    - Строка    - Истина - вызвать исключение если база существует
//
Процедура СоздатьБазу(База,
	                  Знач МодельВосстановления = Неопределено,
	                  Знач ПутьККаталогу = "",
	                  Знач ОшибкаЕслиСуществует = Ложь) Экспорт

	Если БазаСуществует(База, ВариантыСообщенияОСуществованииБД().СообщатьОСуществовании) Тогда
		Если ОшибкаЕслиСуществует Тогда
			ТекстОшибки = СтрШаблон("База ""%1"" уже существует", База);
			ВызватьИсключение ТекстОшибки;
		Иначе
			Возврат;
		КонецЕсли;
	КонецЕсли;

	Если НЕ ЗначениеЗаполнено(МодельВосстановления) Тогда
		МодельВосстановления = МоделиВосстановленияБД().Полная;
	КонецЕсли;

	ПутьККаталогу = ФС.ПолныйПуть(ПутьККаталогу);

	Если ЗначениеЗаполнено(ПутьККаталогу) Тогда
		ТекстЗапроса = СтрШаблон("""USE [master];
	                         |
	                         |CREATE DATABASE [%1]
	                         |ON
	                         |( NAME = %1,
	                         |  FILENAME = '%2%1.mdf')
	                         |LOG ON
	                         |( NAME = %1_log,
	                         |  FILENAME = '%2%1_log.ldf');
	                         |
	                         |ALTER DATABASE [%1]
	                         |SET RECOVERY %3"" ",
	                         База,
	                         ПутьККаталогу,
	                         МодельВосстановления);
	Иначе
		ТекстЗапроса = СтрШаблон("""USE [master];
	                         |
	                         |CREATE DATABASE [%1];
	                         |
	                         |ALTER DATABASE [%1]
	                         |SET RECOVERY %2"" ",
	                         База,
	                         МодельВосстановления);
	КонецЕсли;

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка создания базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // СоздатьБазу()

// Процедура выполняет команду удаления базы на сервере СУБД
//
// Параметры:
//   База                      - Строка    - имя базы данных
//   ОшибкаЕслиНеСуществует    - Строка    - Истина - вызвать исключение если база не существует
//
Процедура УдалитьБазу(База, ОшибкаЕслиНеСуществует = Ложь) Экспорт

	Если НЕ БазаСуществует(База, ВариантыСообщенияОСуществованииБД().СообщатьОбОтсутствии) Тогда
		Если ОшибкаЕслиНеСуществует Тогда
			ТекстОшибки = СтрШаблон("База ""%1"" не обнаружена", База);
			ВызватьИсключение ТекстОшибки;
		Иначе
			Возврат;
		КонецЕсли;
	КонецЕсли;

	ТекстЗапроса = СтрШаблон("""USE [master];
	                         |
	                         |ALTER DATABASE [%1] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
	                         |
	                         |DROP DATABASE [%1]"" ",
	                         База);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка удаления базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // УдалитьБазу()

// Процедура переводит базу данных в однопользовательский режим
//
// Параметры:
//   База                      - Строка    - имя базы данных
//   ОшибкаЕслиНеСуществует    - Строка    - Истина - вызвать исключение если база не существует
//
Процедура УстановитьОднопользовательскийРежимБазы(База, ОшибкаЕслиНеСуществует = Истина) Экспорт

	Если НЕ БазаСуществует(База, ВариантыСообщенияОСуществованииБД().СообщатьОбОтсутствии) Тогда
		Если ОшибкаЕслиНеСуществует Тогда
			ТекстОшибки = СтрШаблон("База ""%1"" не обнаружена", База);
			ВызватьИсключение ТекстОшибки;
		Иначе
			Возврат;
		КонецЕсли;
	КонецЕсли;

	ТекстЗапроса = СтрШаблон("""USE [master];
	                         |
	                         |ALTER DATABASE [%1] SET SINGLE_USER WITH ROLLBACK IMMEDIATE"" ",
	                         База);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка установки однопользовательского режима для базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // УстановитьОднопользовательскийРежимБазы()

// Процедура переводит базу данных в многопользовательский режим
//
// Параметры:
//   База                      - Строка    - имя базы данных
//   ОшибкаЕслиНеСуществует    - Строка    - Истина - вызвать исключение если база не существует
//
Процедура УстановитьМногопользовательскийРежимБазы(База, ОшибкаЕслиНеСуществует = Истина) Экспорт

	Если НЕ БазаСуществует(База, ВариантыСообщенияОСуществованииБД().СообщатьОбОтсутствии) Тогда
		Если ОшибкаЕслиНеСуществует Тогда
			ТекстОшибки = СтрШаблон("База ""%1"" не обнаружена", База);
			ВызватьИсключение ТекстОшибки;
		Иначе
			Возврат;
		КонецЕсли;
	КонецЕсли;

	ТекстЗапроса = СтрШаблон("""USE [master];
	                         |
	                         |ALTER DATABASE [%1] SET MULTI_USER"" ",
	                         База);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка установки многопользовательского режима для базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // УстановитьМногопользовательскийРежимБазы()

// Функция получает описание базы данных
//
// Параметры:
//   База    - Строка    - имя базы данных
//
// Возвращаемое значение:
//   Структура                              - описание базы данных
//     *Имя                                   - Строка  - имя базы данных (name)
//     *Ид                                    - Число   - числовой идентификатор базы (database_id)
//     *ФизическоеИмя                         - Строка  - физическое имя базы (physical_database_name)
//     *Владелец                              - Строка  - пользователь - владелец базы (db owner)
//     *ДатаСоздания                          - Дата    - дата создания базы (create_date)
//     *РежимСовместимости                    - Число   - режим совместимости базы (версия MS SQL) (compatibility_level)
//     *ЯзыковыеУстановки                     - Строка  - используемые языковые установки (collation_name)
//     *РежимДоступа                          - Булево  - режим пользовательского доступа к базе
//                                                        (SINGLE_USER, MULTI_USER) (user_access_desc)
//     *ТолькоДляЧтения                       - Булево  - флаг режима только для чтения (is_read_only)
//     *Состояние                             - Строка  - состояние базы (ONLINE, OFFLINE) (state_desc)
//     *РежимОжидания                         - Булево  - флаг нахождения базы в режиме ожидания (is_in_standby)
//     *РежимИзоляцииСнимков                  - Булево  - флаг использования режима изоляции снимков
//                                                        (snapshot_isolation_state)
//     *РежимФиксированногоЧтенияСнимков      - Булево  - флаг использования фиксированного чтения снимков
//                                                        (is_read_committed_snapshot_on)
//     *МодельВосстановления                  - Строка  - модель восстановления базы (FULL, SIMPLE, BULK_LOGGED)
//                                                        (recovery_model_desc)
//     *АвтоСозданиеСтатистики                - Булево  - флаг автоматического создания статистики
//                                                        (is_auto_create_stats_on)
//     *АвтоСозданиеСтатистикиИнкрементально  - Булево  - флаг автоматического инкрементального создания статистики
//                                                        (is_auto_create_stats_incremental_on)
//     *АвтоОбновлениеСтатистики              - Булево  - флаг автоматического обновления статистики
//                                                        (is_auto_update_stats_on)
//     *АвтоОбновлениеСтатистикиАсинх         - Булево  - флаг автоматического асинхронного обновления статистики
//                                                        (is_auto_update_stats_async_on)
//     *ПолнотекстовыйПоиск                   - Булево  - флаг использования полнотекстового поиска
//                                                        (is_fulltext_enabled)
//     *Шифрование                            - Булево  - флаг использования шифрования базы (is_encrypted)
//
Функция ПолучитьОписаниеБазы(База) Экспорт

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         |
	                         |SELECT
	                         |  db.[name] AS Name,
	                         |  [database_id] AS Database_id,
	                         |  [physical_database_name] AS Physical_name,
	                         |  logins.[name] AS Login,
	                         |  [create_date] AS Create_date,
	                         |  [compatibility_level] AS Compatibility_level,
	                         |  [collation_name] AS Collation_name,
	                         |  [user_access_desc] AS User_access,
	                         |  [is_read_only] AS Read_only,
	                         |  [state_desc] AS State,
	                         |  [is_in_standby] AS Standby,
	                         |  [snapshot_isolation_state] AS Snapshot_isolation,
	                         |  [is_read_committed_snapshot_on] AS Read_committed_snapshot,
	                         |  [recovery_model_desc] AS Recovery_model,
	                         |  [is_auto_create_stats_on] AS Auto_create_stats,
	                         |  [is_auto_create_stats_incremental_on] AS Auto_create_stats_incremental,
	                         |  [is_auto_update_stats_on] AS Auto_update_stats,
	                         |  [is_auto_update_stats_async_on] AS Auto_update_stats_async,
	                         |  [is_fulltext_enabled] AS Fulltext,
	                         |  [is_encrypted] AS Encrypted
	                         |FROM sys.databases AS db
                             |LEFT JOIN sys.syslogins AS logins
                             |ON db.owner_sid = logins.sid
	                         |
	                         |WHERE db.name = '%1';
	                         |
	                         |SET NOCOUNT OFF;"" ",
	                         База);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса, "|", Истина);
	
	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения описания базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Разделитель = "---";
	Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
	Если Поз > 0 Тогда
		РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
	КонецЕсли;

	ПоляРезультата = "Имя
	                 |Ид
	                 |ФизическоеИмя
	                 |Владелец
	                 |ДатаСоздания
	                 |РежимСовместимости
	                 |ЯзыковыеУстановки
	                 |РежимДоступа
	                 |ТолькоДляЧтения
	                 |Состояние
	                 |РежимОжидания
	                 |РежимИзоляцииСнимков
	                 |РежимФиксированногоЧтенияСнимков
	                 |МодельВосстановления
	                 |АвтоСозданиеСтатистики
	                 |АвтоСозданиеСтатистикиИнкрементально
	                 |АвтоОбновлениеСтатистики
	                 |АвтоОбновлениеСтатистикиАсинх
	                 |ПолнотекстовыйПоиск
	                 |Шифрование";
	ПоляРезультата = СтрРазделить(ПоляРезультата, Символы.ПС, Ложь);

	Текст = Новый ТекстовыйДокумент();
	Текст.УстановитьТекст(РезультатЗапроса);
	СтрокаРезультатаЗапроса = Текст.ПолучитьСтроку(Текст.КоличествоСтрок());
	
	Результат = СтрокаРезультатаЗапросаВСтруктуру(СтрокаРезультатаЗапроса, ПоляРезультата);

	Для Каждого ТекЭлемент Из Результат Цикл
		Если ТекЭлемент.Ключ = "ДатаСоздания" Тогда
			Результат[ТекЭлемент.Ключ] = ДатаИзСтроки(ТекЭлемент.Значение);
		ИначеЕсли СтрНайти("ТолькоДляЧтения,
		                   |РежимОжидания,
		                   |РежимИзоляцииСнимков,
		                   |РежимФиксированногоЧтенияСнимков,
		                   |АвтоСозданиеСтатистики,
		                   |АвтоСозданиеСтатистикиИнкрементально,
		                   |АвтоОбновлениеСтатистики,
		                   |АвтоОбновлениеСтатистикиАсинх,
		                   |ПолнотекстовыйПоиск,
		                   |Шифрование", ТекЭлемент.Ключ) > 0 Тогда
			Результат[ТекЭлемент.Ключ] = (ТекЭлемент.Значение = "1");
		КонецЕсли;
	КонецЦикла;

	Возврат Результат;

КонецФункции // ПолучитьОписаниеБазы()

// Процедура устанавливает модель восстановления базы
//
// Параметры:
//   База                    - Строка    - имя базы данных
//   МодельВосстановления    - Строка    - новая модель восстановления (FULL, SIMPLE, BULK_LOGGED)
//
Процедура УстановитьМодельВосстановления(База, Знач МодельВосстановления = Неопределено) Экспорт

	МодельВосстановления = ВРег(МодельВосстановления);

	Если Найти("FULL,SIMPLE,BULK_LOGGED", МодельВосстановления) = 0 Тогда
		ТекстОшибки = СтрШаблон("Указана некорректная модель восстановления ""%1""
		                        | (возможные значения: ""FULL"", ""SIMPLE"", ""BULK_LOGGED"")!",
		                        МодельВосстановления);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ТекстЗапроса = СтрШаблон("""USE [master];
	                         |
	                         |ALTER DATABASE [%1]
	                         |SET RECOVERY %2"" ",
	                         База,
	                         МодельВосстановления);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);
	
	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения модели восстановления базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // УстановитьМодельВосстановления()

// Процедура изменяет владельца базы
//
// Параметры:
//   База                - Строка    - имя базы данных
//   НовыйВладелец       - Строка    - новый владелец базы
//
Процедура УстановитьВладельцаБазы(База, НовыйВладелец) Экспорт

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	РезультатЗапроса = "";
	ТекстЗапроса = СтрШаблон("""ALTER AUTHORIZATION ON DATABASE::%1 TO %2""", База, НовыйВладелец);

	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка изменения владельца базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // УстановитьВладельцаБазы()

// Процедура выполняет сжатие базы (shrink)
//
// Параметры:
//   База                - Строка    - имя базы данных
//
Процедура СжатьБазу(База) Экспорт

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ТекстЗапроса = СтрШаблон("""DBCC SHRINKDATABASE(N'%1', 0)""", База);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка сжатия (shrink) файла данных базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // СжатьБазу()

// Процедура выполняет сжатие файла лог (shrink)
//
// Параметры:
//   База                - Строка    - Имя базы данных
//
Процедура СжатьФайлЖурналаТранзакций(База) Экспорт

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);
	
	ЛогическоеИмяФайлаЖурнала = ПолучитьЛогическоеИмяФайлаВБазе(База, "L");

	ТекстЗапроса = СтрШаблон("""USE [%1];
	                         |
	                         |DBCC SHRINKFILE(N'%2', 0, TRUNCATEONLY); "" ",
	                         База,
	                         ЛогическоеИмяФайлаЖурнала);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка сжатия (shrink) файла журнала базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // СжатьФайлЖурналаТранзакций()

// Процедура выполняет выполняет компрессию базы и индексов на уровне страниц (DATA_COMPRESSION = PAGE)
//
// Параметры:
//   База                  - Строка    - имя базы данных
//   КомпрессияТаблиц      - Булево    - Истина - будет выполнена компрессия таблиц базы
//   КомпрессияИндексов    - Булево    - Истина - будет выполнена компрессия индексов базы
//
Процедура ВключитьКомпрессиюСтраниц(База,
                                    КомпрессияТаблиц = Истина,
                                    КомпрессияИндексов = Истина) Экспорт

	ОписаниеВерсии = ПолучитьВерсиюСУБД();

	Если НЕ ДоступностьФункционалаСУБД("Компрессия", ОписаниеВерсии) Тогда
		Лог.Предупреждение("Для данной версии СУБД ""MS SQL Server %1 %2""
		                   |не доступна функциональность компресии страниц!",
		                   ОписаниеВерсии.Версия,
		                   ОписаниеВерсии.Редакция);
		Возврат;
	КонецЕсли;

	Если НЕ (КомпрессияТаблиц ИЛИ КомпрессияИндексов) Тогда
		Лог.Предупреждение("Не указан флаг включения компрессии страниц для индексов или таблиц!");
		Возврат;
	КонецЕсли;

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ТекстЗапроса = СтрШаблон("""USE [%1];", База);
	Если КомпрессияТаблиц Тогда
		ТекстЗапроса = СтрШаблон("%1%2EXEC sp_MSforeachtable 'ALTER TABLE ? REBUILD WITH (DATA_COMPRESSION = PAGE)'",
		                         ТекстЗапроса,
		                         Символы.ПС);
	КонецЕсли;

	Если КомпрессияИндексов Тогда
		ТекстЗапроса = СтрШаблон("%1%2EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REBUILD WITH (DATA_COMPRESSION = PAGE)'",
		                         ТекстЗапроса,
		                         Символы.ПС);
	КонецЕсли;

	ТекстЗапроса = СтрШаблон("%1""", ТекстЗапроса);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка компресии базы ""%1"": %2%3",
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // ВключитьКомпрессиюСтраниц()

// Процедура создает файл резервной копии базы
//
// Параметры:
//   База                   - Строка    - имя базы данных
//   ПутьКРезервнойКопии    - Строка    - путь к файлу резервной копии
//
Процедура СоздатьРезервнуюКопию(База, Знач ПутьКРезервнойКопии) Экспорт
	
	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ПутьКРезервнойКопии = ФС.ПолныйПуть(ПутьКРезервнойКопии);

	ТекстЗапроса = СтрШаблон("""BACKUP DATABASE [%1] TO DISK = N'%2'
	                         |WITH NOFORMAT, INIT, NAME = N'%1 FULL Backup',
	                         |SKIP,
	                         |NOREWIND,
	                         |NOUNLOAD,
	                         |COMPRESSION,
	                         |STATS = 10"" ",
	                         База,
	                         ПутьКРезервнойКопии);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка резервного копирования базы ""%1"" в файл ""%2"": %3%4",
		                        База,
		                        ПутьКРезервнойКопии,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // СоздатьРезервнуюКопию()

// Процедура выполняет восстановление базы из файла с резервной копией
//
// Параметры:
//   База                   - Строка    - имя базы данных
//   ПутьКРезервнойКопии    - Строка    - путь к файлу резервной копии
//   ПутьКФайлуДанных       - Строка    - путь к файлу базы
//   ПутьКФайлуЖурнала      - Строка    - путь к файлу журнала (transaction log) базы
//   СоздаватьБазу          - Булево    - Истина - будет создана новая база в случае отсутствия
//
Процедура ВосстановитьИзРезервнойКопии(База,
                                     Знач ПутьКРезервнойКопии,
                                     Знач ПутьКФайлуДанных = "",
                                     Знач ПутьКФайлуЖурнала = "",
                                     СоздаватьБазу = Ложь) Экспорт
	
	Если НЕ БазаСуществует(База, ВариантыСообщенияОСуществованииБД().СообщатьОбОтсутствии) Тогда
		Если НЕ СоздаватьБазу Тогда
			ТекстОшибки = СтрШаблон("База ""%1"" не обнаружена", База);
			ВызватьИсключение ТекстОшибки;
		Иначе
			СоздатьБазу(База, МоделиВосстановленияБД().Простая);
		КонецЕсли;
	КонецЕсли;

	ПутьКРезервнойКопии = ФС.ПолныйПуть(ПутьКРезервнойКопии);

	Если ЗначениеЗаполнено(ПутьКФайлуДанных) Тогда
		ПутьКФайлуДанных = ФС.ПолныйПуть(ПутьКФайлуДанных);
	Иначе
		ПутьКФайлуДанных = РасположениеФайловБазПоУмолчанию("D");
	КонецЕсли;

	Если ЗначениеЗаполнено(ПутьКФайлуЖурнала) Тогда
		ПутьКФайлуЖурнала = ФС.ПолныйПуть(ПутьКФайлуЖурнала);
	Иначе
		ПутьКФайлуЖурнала = РасположениеФайловБазПоУмолчанию("L");
	КонецЕсли;
	
	ЛогическоеИмяФайлаДанных = ПолучитьЛогическоеИмяФайлаВРезервнойКопии(ПутьКРезервнойКопии, "D");
	ЛогическоеИмяФайлаЖурнала = ПолучитьЛогическоеИмяФайлаВРезервнойКопии(ПутьКРезервнойКопии, "L");

	ТекстЗапроса = СтрШаблон("""USE [master];
	                         |
	                         |ALTER DATABASE [%1] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
	                         |
	                         |RESTORE DATABASE [%1] FROM  DISK = N'%2' WITH  FILE = 1,
	                         |MOVE N'%3' TO N'%4%1.mdf',
	                         |MOVE N'%5' TO N'%6%1_log.ldf',
	                         |NOUNLOAD,  REPLACE,  STATS = 10;
	                         |
	                         |ALTER DATABASE [%1] SET MULTI_USER"" ",
	                         База,
	                         ПутьКРезервнойКопии,
	                         ЛогическоеИмяФайлаДанных,
	                         ПутьКФайлуДанных,
	                         ЛогическоеИмяФайлаЖурнала,
	                         ПутьКФайлуЖурнала);
	
	РезультатЗапроса = "";	
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка восстановления базы ""%1"" из резервной копии ""%2"": %3%4",
		                        База,
		                        ПутьКРезервнойКопии,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // ВосстановитьИзРезервнойКопии()

// Функция возвращает логическое имя файла в резервной копии
//
// Параметры:
//   ПутьКРезервнойКопии    - Строка    - путь к файлу резервной копии
//   ТипФайла               - Строка    - D - файл данных; L - файл журнала транзакций
//
// Возвращаемое значение:
//   Строка    - логическое имя файла базы в файле резервной копии
//
Функция ПолучитьЛогическоеИмяФайлаВРезервнойКопии(Знач ПутьКРезервнойКопии, Знач ТипФайла = Неопределено) Экспорт
	
	ТипыФайлов = ТипыФайловБД();
	ТипыФайловСокр = ТипыФайловБД(Истина);

	Если НЕ ЗначениеЗаполнено(ТипФайла) Тогда
		ТипФайла = ТипыФайловСокр.Данные;
	КонецЕсли;

	ТипФайла = ВРег(ТипФайла);

	Если ТипФайла = ТипыФайлов.Данные ИЛИ ТипФайла = ТипыФайловСокр.Данные Тогда
		ТипФайла = ТипыФайловСокр.Данные;
		ТипФайлаПредставление = "данных";
	ИначеЕсли ТипФайла = ТипыФайлов.Журнал ИЛИ ТипФайла = ТипыФайловСокр.Журнал Тогда
		ТипФайла = ТипыФайловСокр.Журнал;
		ТипФайлаПредставление = "журнала";
	Иначе
		Возврат Неопределено;
	КонецЕсли;
	
	ПутьКРезервнойКопии = ФС.ПолныйПуть(ПутьКРезервнойКопии);

	ПоляТаблицыФайловРезервнойКопии = ПоляТаблицыФайловРезервнойКопии();

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         |
	                         |DECLARE @T1CTmp TABLE (%1);
	                         |
	                         |INSERT INTO @T1CTmp EXECUTE('RESTORE FILELISTONLY FROM DISK = N''%2''');
	                         |
	                         |SELECT
	                         |	[LogicalName]
	                         |FROM
	                         |	@T1CTmp
	                         |WHERE
	                         |	[Type] = '%3';
	                         |
	                         |SET NOCOUNT OFF;"" ",
	                         ПоляТаблицыФайловРезервнойКопии,
	                         ПутьКРезервнойКопии,
	                         ТипФайла);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если КодВозврата = 0 Тогда
		Разделитель = "---";
		Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
		Если Поз > 0 Тогда
			РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
		КонецЕсли;
	Иначе
		ТекстОшибки = СтрШаблон("Ошибка получения логического имени файла %1 в резервной копии ""%2"": %3%4",
		                        ТипФайлаПредставление,
		                        ПутьКРезервнойКопии,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Возврат РезультатЗапроса;

КонецФункции // ПолучитьЛогическоеИмяФайлаВРезервнойКопии()
	
// Функция возвращает логическое имя файла в базе
//
// Параметры:
//   База        - Строка    - имя базы данных
//   ТипФайла    - Строка    - ROWS - файл базы; LOG - файл журнала транзакций
//
// Возвращаемое значение:
//   Строка     - логическое имя файла базы
//
Функция ПолучитьЛогическоеИмяФайлаВБазе(База, Знач ТипФайла = Неопределено) Экспорт
	
	ТипыФайлов = ТипыФайловБД();
	ТипыФайловСокр = ТипыФайловБД(Истина);

	Если НЕ ЗначениеЗаполнено(ТипФайла) Тогда
		ТипФайла = ТипыФайлов.Данные;
	КонецЕсли;

	Если ТипФайла = ТипыФайлов.Данные ИЛИ ТипФайла = ТипыФайловСокр.Данные Тогда
		ТипФайла = ТипыФайлов.Данные;
		ТипФайлаПредставление = "данных";
	ИначеЕсли ТипФайла = ТипыФайлов.Журнал ИЛИ ТипФайла = ТипыФайловСокр.Журнал Тогда
		ТипФайла = ТипыФайлов.Журнал;
		ТипФайлаПредставление = "журнала";
	Иначе
		ТекстОшибки = СтрШаблон("Некорректно указан тип файла ""%1"" для получения логического имени,
		                        | ожидается ""ROWS (D) ИЛИ LOG (L).",
		                        ТипФайла);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         |
	                         |SELECT
	                         |	[name]
	                         |FROM
	                         |	sys.master_files
	                         |WHERE
	                         |	[database_id]=db_id('%1')
	                         |		AND type_desc='%2';
	                         |
	                         |SET NOCOUNT OFF;"" ",
	                         База,
	                         ТипФайла);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если КодВозврата = 0 Тогда
		Разделитель = "---";
		Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
		Если Поз > 0 Тогда
			РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
		КонецЕсли;
	Иначе
		ТекстОшибки = СтрШаблон("Ошибка получения логического имени файла %1 в базе ""%2"": %3%4",
		                        ТипФайлаПредставление,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Возврат РезультатЗапроса;

КонецФункции // ПолучитьЛогическоеИмяФайлаВБазе()

// Процедура изменяет логическое имя файла базы
//
// Параметры:
//   База        - Строка    - имя базы данных
//   Имя         - Строка    - логическое имя изменяемого файла
//   НовоеИмя    - Строка    - новое логическое имя
//
Процедура ИзменитьЛогическоеИмяФайлаВБазе(База, Имя, НовоеИмя) Экспорт

	Если Имя = НовоеИмя Тогда
		Лог.Предупреждение("Новое логическое имя ""%1"" совпадает со старым ""%2""!", Имя, НовоеИмя);
		Возврат;
	КонецЕсли;

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ТекстЗапроса = СтрШаблон("""USE [master];
	                         |
	                         |ALTER DATABASE [%1]
	                         |MODIFY FILE (NAME = N'%2', NEWNAME = N'%3');"" ",
	                         База,
	                         Имя,
	                         НовоеИмя);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка изменения логического имени файла ""%1"" базы ""%2"" на ""%3"": %4%5",
		                        Имя,
		                        База,
		                        НовоеИмя,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

КонецПроцедуры // ИзменитьЛогическоеИмяФайлаВБазе()

// Функция возвращает путь к расположению по умолчанию для указанного типа файлов базы
//
// Параметры:
//   ТипФайла    - Строка    - ROWS - файл базы; LOG - файл журнала транзакций
//
// Возвращаемое значение:
//   Строка    - путь к расположению по умолчанию
//
Функция РасположениеФайловБазПоУмолчанию(Знач ТипФайла = Неопределено) Экспорт
	
	ТипыФайлов = ТипыФайловБД();
	ТипыФайловСокр = ТипыФайловБД(Истина);

	Если НЕ ЗначениеЗаполнено(ТипФайла) Тогда
		ТипФайла = ТипыФайлов.Данные;
	КонецЕсли;

	Если ТипФайла = ТипыФайлов.Данные ИЛИ ТипФайла = ТипыФайловСокр.Данные Тогда
		ТипФайла = ТипыФайлов.Данные;
		ТипФайлаПредставление = "данных";
	ИначеЕсли ТипФайла = ТипыФайлов.Журнал ИЛИ ТипФайла = ТипыФайловСокр.Журнал Тогда
		ТипФайла = ТипыФайлов.Журнал;
		ТипФайлаПредставление = "журналов";
	Иначе
		Возврат Неопределено;
	КонецЕсли;
	

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         |
	                         |SELECT
	                         |	[physical_name]
	                         |FROM
	                         |	sys.master_files
	                         |WHERE
	                         |	[database_id]=4
	                         |		AND type_desc='%1';
	                         |
	                         |SET NOCOUNT OFF;"" ",
	                         ТипФайла);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если КодВозврата = 0 Тогда
		Разделитель = "---";
		Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
		Если Поз > 0 Тогда
			РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
		КонецЕсли;

		ФайлБазы = Новый Файл(РезультатЗапроса);
		РезультатЗапроса = Сред(ФайлБазы.Путь, 1, СтрДлина(ФайлБазы.Путь) - 1);

	Иначе
		ТекстОшибки = СтрШаблон("Ошибка получения расположения по умолчанию файлов %1: %2%3",
		                        ТипФайлаПредставление,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Возврат РезультатЗапроса;

КонецФункции // РасположениеФайловБазПоУмолчанию()

// Функция возвращает описание установленной версии SQL Server
//
// Возвращаемое значение:
//   Структура                        - описание версии SQL Server
//     *ИмяСервера           - Строка    - имя сервера
//     *ИмяЭкземпляраСУБД    - Строка    - имя экземпляра СУБД на сервере
//     *Редакция             - Строка    - номер редакции
//     *Версия               - Строка    - номер версии
//     *Уровень              - Строка    - уровень продукта
//     *ВерсияМакс           - Строка    - старший номер версии (2000 - 2000 (8)), 2005 - 9,
//                                                               2008 - 10, 2012 - 11, 2014 - 12, 2016 - 13)
//     *Корп                 - Строка    - признак Enterprise версии
//
Функция ПолучитьВерсиюСУБД() Экспорт
	
	ТекстЗапроса = """SET NOCOUNT ON;
	               |SELECT
	               |  SERVERPROPERTY('MachineName') AS ComputerName,
	               |  SERVERPROPERTY('ServerName') AS InstanceName,
	               |  SERVERPROPERTY('Edition') AS Edition,
	               |  SERVERPROPERTY('ProductVersion') AS ProductVersion,
	               |  SERVERPROPERTY('ProductLevel') AS ProductLevel,
	               |  @@VERSION AS FullVersion;
	               |SET NOCOUNT OFF;"" ";

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса, "|", Истина);

	Если КодВозврата = 0 Тогда
		Разделитель = "---";
		Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
		Если Поз > 0 Тогда
			РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
		КонецЕсли;
	Иначе
		ТекстОшибки = СтрШаблон("Ошибка получения версии СУБД: %1%2",
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	ИмяСервера           = 0;
	ИмяЭкземпляраСУБД    = 1;
	Редакция             = 2;
	Версия               = 3;
	Уровень              = 4;
	Представление        = 5;
	
	// 2000 - 2000 (8)), 2005 - 9, 2008 - 10, 2012 - 11, 2014 - 12, 2016 - 13, 2017 - 14, 2019 - 15
	МассивВерсий = СтрРазделить("2000-8,9,10,11,12,13,14,15", ",");

	СоответствиеВерсий = Новый Соответствие();

	Для Каждого ТекВерсия Из МассивВерсий Цикл
		ЧастиВерсии = СтрРазделить(ТекВерсия, "-");

		КоличествоЧастей = ЧастиВерсии.Количество();
		Если КоличествоЧастей = 1 Тогда
			СоответствиеВерсий.Вставить(ЧастиВерсии[0], Число(ЧастиВерсии[0]));
		ИначеЕсли КоличествоЧастей > 1 Тогда
			СоответствиеВерсий.Вставить(ЧастиВерсии[0], Число(ЧастиВерсии[1]));
		Иначе
			Возврат Неопределено;
		КонецЕсли;	
	КонецЦикла;
	
	СтруктураРезультата = Новый Структура();

	МассивЗначений = СтрРазделить(РезультатЗапроса, "|", Ложь);

	СтруктураРезультата.Вставить("ИмяСервера"       , МассивЗначений[ИмяСервера]);
	СтруктураРезультата.Вставить("ИмяЭкземпляраСУБД", МассивЗначений[ИмяЭкземпляраСУБД]);
	СтруктураРезультата.Вставить("Редакция"         , МассивЗначений[Редакция]);
	СтруктураРезультата.Вставить("Версия"           , МассивЗначений[Версия]);
	СтруктураРезультата.Вставить("Уровень"          , МассивЗначений[Уровень]);
	СтруктураРезультата.Вставить("Представление"    , МассивЗначений[Представление]);
	
	МассивВерсии = СтрРазделить(СтруктураРезультата["Версия"], ".");
	СтруктураРезультата.Вставить("ВерсияМакс"       , СоответствиеВерсий[МассивВерсии[0]]);

	СтруктураРезультата.Вставить("Корп"             , СтрНайти(ВРег(СтруктураРезультата["Редакция"]), "ENTERPRISE") > 0);

	Возврат СтруктураРезультата;

КонецФункции // ПолучитьВерсиюСУБД()

// Функция - возвращает описание занимаемого места в базе MS SQL Server
//
// Параметры:
//   База    - Строка    - имя базы данных
//
// Возвращаемое значение:
//  Структура                       - описание занимаего места
//     *РазмерБазы         - Число    - размер текущей базы данных в байтах, включает файлы данных и журналов
//     *Свободно           - Число    - место в базе данных, не зарезервированное для объектов базы данных
//     *Зарезервировано    - Число    - общий объем, выделенный объектам в базе данных
//     *Данные             - Число    - зарезервированный объем, используемый данными
//     *Индексы            - Число    - зарезервированный объем, используемый индексами
//     *НеИспользуется     - Число    - объем, зарезервированный для объектов в базе данных,
//                                      но пока не используемый
//     *ЖурналВсего        - Число    - полный объем журнала транзакций
//     *ЖурналИспользуется - Число    - используемый объем журнала транзакций
//
Функция ЗанимаемоеБазойМесто(База) Экспорт

	ТекстЗапроса = СтрШаблон("""USE [%1];
	                         |
	                         |SET NOCOUNT ON;
	                         |
	                         |declare @space_usage_data table(
	                         |database_name nvarchar(128),
	                         |database_size varchar(18),
	                         |unallocated_space varchar(18),
	                         |reserved varchar(18),
	                         |data varchar(18),
	                         |index_size varchar(18),
	                         |unused varchar(18))
	                         |INSERT INTO @space_usage_data exec sp_spaceused @oneresultset=1
	                         |
	                         |SELECT
	                         |space_usage_data.database_name,
	                         |CONVERT(dec(15,2), LTRIM(LEFT(space_usage_data.database_size, CHARINDEX('MB', space_usage_data.database_size) - 1))) * 1048576 AS database_size,
	                         |CONVERT(dec(15,2), LTRIM(LEFT(space_usage_data.unallocated_space, CHARINDEX('MB', space_usage_data.unallocated_space) - 1))) * 1048576 AS unallocated_space,
	                         |CONVERT(dec(15,2), LTRIM(LEFT(space_usage_data.reserved, CHARINDEX('KB', space_usage_data.reserved) - 1))) * 1024 AS reserved,
	                         |CONVERT(dec(15,2), LTRIM(LEFT(space_usage_data.data, CHARINDEX('KB', space_usage_data.data) - 1))) * 1024 AS data_size,
	                         |CONVERT(dec(15,2), LTRIM(LEFT(space_usage_data.index_size, CHARINDEX('KB', space_usage_data.index_size) - 1))) * 1024 AS index_size,
	                         |CONVERT(dec(15,2), LTRIM(LEFT(space_usage_data.unused, CHARINDEX('KB', space_usage_data.unused) - 1))) * 1024 AS unused,
	                         |CONVERT(dec(15,2), space_usage_log.total_log_size_in_bytes) AS log_size_total,
	                         |CONVERT(dec(15,2), space_usage_log.used_log_space_in_bytes) AS log_size_used
	                         |FROM @space_usage_data AS space_usage_data
	                         |LEFT JOIN sys.databases AS dbs
	                         |on space_usage_data.database_name = dbs.name
	                         |LEFT JOIN sys.dm_db_log_space_usage AS space_usage_log
	                         |on dbs.database_id = space_usage_log.database_id
	                         |
	                         |SET NOCOUNT OFF"" ",
	                         База);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса, "|", Истина);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения информации о занимаемом месте для базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Разделитель = "---";
	Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
	Если Поз > 0 Тогда
		РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
	КонецЕсли;

	ПоляРезультата = "Имя
	                 |РазмерБазы
	                 |Свободно
	                 |Зарезервировано
	                 |Данные
	                 |Индексы
	                 |НеИспользуется
	                 |ЖурналВсего
	                 |ЖурналИспользуется";
	ПоляРезультата = СтрРазделить(ПоляРезультата, Символы.ПС, Ложь);

	Текст = Новый ТекстовыйДокумент();
	Текст.УстановитьТекст(РезультатЗапроса);
	СтрокаРезультатаЗапроса = Текст.ПолучитьСтроку(Текст.КоличествоСтрок());

	Результат = СтрокаРезультатаЗапросаВСтруктуру(СтрокаРезультатаЗапроса, ПоляРезультата);

	Возврат Результат;

КонецФункции // ЗанимаемоеБазойМесто()

// Функция - возвращает список таблиц базы, соответствующих фильтру
//
// Параметры:
//   База                   - Строка    - имя базы данных
//   ТолькоКоличество       - Булево    - Истина - возвращать только количество таблиц базы
//   ФильтрТаблицПоИмени    - Строка    - фильтр имен таблиц в формате для оператора "LIKE"
//
// Возвращаемое значение:
//  Соответствие    - список таблиц базы
//
Функция ТаблицыБазы(База, ТолькоКоличество = Ложь, ФильтрТаблицПоИмени = "") Экспорт

	ШаблонЗапроса = """SET NOCOUNT ON;
	                |SELECT
	                |%2
	                |FROM [%1].sys.objects T
	                |WHERE
	                |%3
	                |SET NOCOUNT OFF;"" ";

	Поля = "T.Name AS [Table]";
	Если ТолькоКоличество Тогда
		Поля = "COUNT(T.Name) AS TableCount";
	КонецЕсли;

	Условие = "T.type = 'U'";
	Если ЗначениеЗаполнено(ФильтрТаблицПоИмени) Тогда
		Условие = СтрШаблон("%1 AND T.Name LIKE '%2'", Условие, ФильтрТаблицПоИмени);
	КонецЕсли;

	ТекстЗапроса = СтрШаблон(ШаблонЗапроса, База, Поля, Условие);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения таблиц базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Если ТолькоКоличество Тогда
		Возврат Число(РезультатЗапроса);
	КонецЕсли;

	Разделитель = "---";
	Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
	Если Поз > 0 Тогда
		РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
	КонецЕсли;

	Таблицы = Новый Массив();

	Текст = Новый ТекстовыйДокумент();
	Текст.УстановитьТекст(РезультатЗапроса);
	
	Для й = 1 По Текст.КоличествоСтрок() Цикл
		ИмяТаблицы = СокрЛП(Текст.ПолучитьСтроку(й));
		Если НЕ ЗначениеЗаполнено(ИмяТаблицы) Тогда
			Продолжить;
		КонецЕсли;

		Таблицы.Добавить(ИмяТаблицы);
	КонецЦикла;

	Возврат Таблицы;

КонецФункции // ТаблицыБазы()

// Функция - возвращает список таблиц в базе MS SQL Server и их показатели использования
//
// Параметры:
//   База                   - Строка    - имя базы данных
//   ФильтрТаблицПоИмени    - Строка    - фильтр имен таблиц в формате для оператора "LIKE"
//   СтатистикаОпераций     - Булево    - Истина - в результат будет включена статистика по операциям с таблицами
//                                        (для больших баз - может занять много времени)
//
// Возвращаемое значение:
//  Массив из Структура                   - таблицы и показатели использования
//     *Таблица                 - Строка    - имя таблицы
//     *КоличествоСтрок         - Число     - количество строк в таблице
//     *ВсегоЗанято             - Число     - общий объем заниаемого места (байт)
//     *Используется            - Число     - объем, используемый данными (байт)
//     *НеИспользуется          - Число     - не используемый объем (байт)
//     *ОперацийЧтения          - Число     - количество операций чтения (read)
//     *ОперацийВыборки         - Число     - количество операций выборки (select)
//     *ОперацийСканирования    - Число     - количество операций сканирования (scan)
//     *ОперацийПоиска          - Число     - количество операций поиска (seek)
//     *ОперацийЗаписи          - Число     - количество операций записи (write)
//
Функция ПоказателиИспользованияТаблицБазы(База, ФильтрТаблицПоИмени = "", СтатистикаОпераций = Ложь) Экспорт

	ШаблонЗапроса = """SET NOCOUNT ON;
	                |
	                | SELECT
	                | Tables.Name AS TableName,
	                | Partitions.Rows AS RowCounts,
	                | SUM(AllocationUnits.total_pages) * 8192 AS TotalSpace,
	                | SUM(AllocationUnits.used_pages) * 8192 AS UsedSpace,
	                | (SUM(AllocationUnits.total_pages) - SUM(AllocationUnits.used_pages)) * 8192 AS UnusedSpace,
	                | %2 AS Reads,
	                | %3 AS Seeks,
	                | %4 AS Scans,
	                | %5 AS Lookups,
	                | %6 AS Writes
	                | FROM
	                | [%1].sys.objects AS Tables
	                | INNER JOIN [%1].sys.indexes AS Indexes
	                | ON Tables.object_id = Indexes.object_id
	                | INNER JOIN [%1].sys.partitions AS Partitions
	                | ON Indexes.object_id = Partitions.object_id
	                | AND Indexes.index_id = Partitions.index_id
	                | INNER JOIN [%1].sys.allocation_units AS AllocationUnits
	                | ON Partitions.partition_id = AllocationUnits.container_id
	                | %7
	                | WHERE
	                | Tables.type = 'U'
	                | AND Tables.is_ms_shipped = 0
	                | AND Indexes.object_id > 255
	                |%8
	                | GROUP BY
	                | Tables.Name,
	                | Partitions.Rows
	                | ORDER BY
	                | Tables.Name;
	                |
	                | SET NOCOUNT OFF;"" ";

	ТекстОперацийЧтения = "NULL";
	ТекстОперацийВыборки = "NULL";
	ТекстОперацийСканирования = "NULL";
	ТекстОперацийПоиска = "NULL";
	ТекстОперацийЗаписи = "NULL";
	ТекстСоединенияСтатистики = "";

	Если СтатистикаОпераций Тогда
		ТекстОперацийЧтения       = "SUM(Stats.user_seeks + Stats.user_scans + Stats.user_lookups)";
		ТекстОперацийВыборки      = "SUM(Stats.user_seeks)";
		ТекстОперацийСканирования = "SUM(Stats.user_scans)";
		ТекстОперацийПоиска       = "SUM(Stats.user_lookups)";
		ТекстОперацийЗаписи       = "SUM(Stats.user_updates)";
		ТекстСоединенияСтатистики = СтрШаблон("LEFT OUTER JOIN [%1].sys.dm_db_index_usage_stats AS Stats
		                                      | ON Tables.object_id = Stats.object_id",
		                                      База);
	КонецЕсли;

	Условие = "";
	Если ЗначениеЗаполнено(ФильтрТаблицПоИмени) Тогда
		Условие = СтрШаблон(" AND Tables.Name LIKE '%1'", ФильтрТаблицПоИмени);
	КонецЕсли;

	ТекстЗапроса = СтрШаблон(ШаблонЗапроса,
	                         База,
	                         ТекстОперацийЧтения,
	                         ТекстОперацийВыборки,
	                         ТекстОперацийСканирования,
	                         ТекстОперацийПоиска,
	                         ТекстОперацийЗаписи,
	                         ТекстСоединенияСтатистики,
	                         Условие);
	
	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса, "|", Истина);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения информации о показателях использования таблиц
		                        | для базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Разделитель = "---";
	Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
	Если Поз > 0 Тогда
		РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
	КонецЕсли;

	ПоказателиТаблиц = Новый Массив();
	
	Текст = Новый ТекстовыйДокумент();
	Текст.УстановитьТекст(РезультатЗапроса);
	
	ПоляРезультата = "Таблица
	                 |КоличествоСтрок
	                 |ВсегоЗанято
	                 |Используется
	                 |НеИспользуется
	                 |ОперацийЧтения
	                 |ОперацийВыборки
	                 |ОперацийСканирования
	                 |ОперацийПоиска
	                 |ОперацийЗаписи";
	 ПоляРезультата = СтрРазделить(ПоляРезультата, Символы.ПС, Ложь);

	Для й = 1 По Текст.КоличествоСтрок() Цикл

		СтрокаРезультатаЗапроса = Текст.ПолучитьСтроку(й);
		Если НЕ ЗначениеЗаполнено(СтрокаРезультатаЗапроса) Тогда
			Продолжить;
		КонецЕсли;

		ПоказателиТаблицы = СтрокаРезультатаЗапросаВСтруктуру(СтрокаРезультатаЗапроса, ПоляРезультата);

		ПоказателиТаблиц.Добавить(ПоказателиТаблицы);

	КонецЦикла;

	Возврат ПоказателиТаблиц;

КонецФункции // ПоказателиИспользованияТаблицБазы()

// Функция - возвращает список колонок базы, соответствующих фильтру
//
// Параметры:
//   База                    - Строка    - имя базы данных
//   ФильтрТаблицПоИмени     - Строка    - фильтр имен таблиц в формате для оператора "LIKE"
//   ФильтрКолонокПоИмени    - Строка    - фильтр имен колонок в формате для оператора "LIKE"
//
// Возвращаемое значение:
//   Соответствие    - список колонок базы
//
Функция КолонкиБазы(База, ФильтрТаблицПоИмени = "", ФильтрКолонокПоИмени = "") Экспорт

	ШаблонЗапроса = """SET NOCOUNT ON;
	                | SELECT
	                | T.Name AS [Table],
	                | C.name AS [Field]
	                | FROM [%1].sys.objects T
	                | LEFT JOIN [%1].sys.columns C
	                | ON T.object_id = C.object_id
	                |WHERE
	                | %2
	                | SET NOCOUNT OFF;"" ";

	Условие = "T.type = 'U'";
	Если ЗначениеЗаполнено(ФильтрТаблицПоИмени) Тогда
		Условие = СтрШаблон("%1 AND T.Name LIKE '%2'", Условие, ФильтрТаблицПоИмени);
	КонецЕсли;

	Если ЗначениеЗаполнено(ФильтрКолонокПоИмени) Тогда
		Условие = СтрШаблон("%1 AND C.Name LIKE '%2'", Условие, ФильтрКолонокПоИмени);
	КонецЕсли;

	ТекстЗапроса = СтрШаблон(ШаблонЗапроса, База, Условие);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса, "|", Истина);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения списка колонок базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса);
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Разделитель = "---";
	Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
	Если Поз > 0 Тогда
		РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
	КонецЕсли;

	Колонки = Новый Массив();

	Текст = Новый ТекстовыйДокумент();
	Текст.УстановитьТекст(РезультатЗапроса);

	Для й = 1 По Текст.КоличествоСтрок() Цикл
		Значения = СтрРазделить(Текст.ПолучитьСтроку(й), "|", Ложь);

		ОписаниеКолонки = Новый Структура();
		ОписаниеКолонки.Вставить("Таблица", СокрЛП(Значения[0]));
		ОписаниеКолонки.Вставить("Колонка", СокрЛП(Значения[1]));

		Колонки.Добавить(ОписаниеКолонки);
	КонецЦикла;

	Возврат Колонки;

КонецФункции // КолонкиБазы()

// Функция - возвращает версию формата конфигурации 1С
//
// Параметры:
//   База    - Строка    - имя базы данных
//
// Возвращаемое значение:
//   Структура            - описание версии формата конфигурации
//     *Версия                      - Число     - номер версии формата конфигурации
//     *ТребуемаяВерсияПлатформы    - Строка    - минимальная версия платформы 1С
//
Функция ВерсияФорматаКонфигурации1С(База) Экспорт

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         | SELECT
	                         | [IBVersion],
	                         | [PlatformVersionReq]
	                         | FROM %1.[dbo].[IBVersion];
	                         |SET NOCOUNT OFF;"" ",
	                         База);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса, "|", Истина);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения версия формата конфигурации 1С базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Разделитель = "---";
	Поз = СтрНайти(РезультатЗапроса, Разделитель, НаправлениеПоиска.FromEnd);
	Если Поз > 0 Тогда
		РезультатЗапроса = СокрЛП(Сред(РезультатЗапроса, Поз + СтрДлина(Разделитель)));
	КонецЕсли;

	Результат = Новый Структура();

	Текст = Новый ТекстовыйДокумент();
	Текст.УстановитьТекст(РезультатЗапроса);
	
	МассивЗначений = СтрРазделить(Текст.ПолучитьСтроку(1), "|", Ложь);

	Результат.Вставить("Версия", Число(МассивЗначений[0]));
	Результат.Вставить("ТребуемаяВерсияПлатформы", МассивЗначений[1]);

	Возврат Результат;

КонецФункции // ВерсияФорматаКонфигурации1С()

// Функция - возвращает версию формата конфигурации 1С
//
// Параметры:
//   База       - Строка    - имя базы данных
//   ИдФайла    - Строка    - идентификатор файла конфигурации 1С
//
// Возвращаемое значение:
//   Структура            - описание версии формата конфигурации
//     *Версия                      - Число     - номер версии формата конфигурации
//     *ТребуемаяВерсияПлатформы    - Строка    - минимальная версия платформы 1С
//
Функция ФайлКонфигурации1С(База, ИдФайла) Экспорт

	БазаСуществует(База, ВариантыСообщенияОСуществованииБД().ИсключениеПриОтсутствии);

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         | SELECT
	                         | [BinaryData]
	                         | FROM %1.[dbo].[Config]
	                         | WHERE [FileName] = '%2'
	                         | FOR XML RAW, BINARY BASE64;
	                         |SET NOCOUNT OFF;"" ",
	                         База,
	                         ИдФайла);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения корневого файла конфигурации 1С базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	НормализоватьXML(РезультатЗапроса);

	ЗначенияАтрибутов = Новый Соответствие();

	Парсер = Новый ЧтениеXML;
	Парсер.УстановитьСтроку(РезультатЗапроса);
 
	Пока Парсер.Прочитать() Цикл
		Если Парсер.ТипУзла = ТипУзлаXML.НачалоЭлемента И ВРег(Парсер.Имя) = "ROW" Тогда
			ЗначенияАтрибутов = ЗначенияАтрибутов(Парсер);
			Прервать;
		КонецЕсли;
	КонецЦикла;
 
	Парсер.Закрыть();

	Данные = ЗначенияАтрибутов["BINARYDATA"];

	Если НЕ ЗначениеЗаполнено(Данные) Тогда
		Данные = "";
	КонецЕсли;

	Возврат Base64Значение(Данные);

КонецФункции // ФайлКонфигурации1С()

// Функция - возвращает количество записей в таблице конфигурации информационной базы 1С
//
// Параметры:
//   База          - Строка    - имя базы данных
//   ИдОбъектов    - Число     - массив идентификаторов объектов метаданных,
//                               если не указан, считываются все записи
//
// Возвращаемое значение:
//   Число    - количество записей в таблице конфигурации информационной базы 1С
//
Функция КоличествоОбъектовКонфигурацииБазы1С(База, ИдОбъектов = "") Экспорт

	ОтборПоИд = ОтборОбъектовКонфигурации1СПоИд(ИдОбъектов);

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         | %1
	                         | SELECT
	                         | COUNT(Config.[FileName])
	                         | FROM %2.[dbo].[Config] AS Config
	                         | %3
	                         | WHERE CHARINDEX('.', Config.[FileName]) = 0
	                         | SET NOCOUNT OFF;"" ",
	                         ОтборПоИд.ТаблицаОтбора,
	                         База,
	                         ОтборПоИд.Отбор);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения количества записей в таблице ""Config"" базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	Возврат Число(РезультатЗапроса);

КонецФункции // КоличествоОбъектовКонфигурацииБазы1С()

// Функция - читает таблицу Config базы 1С
//
// Параметры:
//   База            - Строка    - имя базы данных
//   ИдОбъектов      - Число     - массив идентификаторов объектов метаданных,
//                                 если не указан, считываются все записи
//   Смещение        - Число     - смещение от начала результата в количестве строк
//                                 если не указан, то с начала результата
//   ПорцияЧтения    - Число     - количество строк таблицы Config читаемое за 1 запрос
//                                 если не указан, считываются все записи начиная со смещения
//
// Возвращаемое значение:
//   Соответствие    - соответствия UUID метаданных и имен метаданных
//
Функция ОбъектыКонфигурацииБазы1С(База, ИдОбъектов = Неопределено, Смещение = 0, ПорцияЧтения = 0) Экспорт

	ОтборПоИд = ОтборОбъектовКонфигурации1СПоИд(ИдОбъектов);

	ОтборПервых = СтрШаблон("FETCH NEXT %1 ROWS ONLY", ПорцияЧтения);

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         | %1
	                         | SELECT
	                         | Config.[FileName] AS FileName,
	                         | Config.[BinaryData] AS BinaryData
	                         | FROM %2.[dbo].[Config] AS Config
	                         | %3
	                         | WHERE CHARINDEX('.', Config.[FileName]) = 0
	                         | ORDER BY Config.[FileName] OFFSET %4 ROWS %5
	                         | FOR XML RAW, BINARY BASE64
	                         | SET NOCOUNT OFF;"" ",
	                         ОтборПоИд.ТаблицаОтбора,
	                         База,
	                         ОтборПоИд.Отбор,
	                         Смещение,
	                         ОтборПервых);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения объектов конфигурации 1С базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	НормализоватьXML(РезультатЗапроса);
	
	ОбъектыКонфигурации = Новый Соответствие();

	ДлинаИд = 36;
	
	Парсер = Новый ЧтениеXML;
	Парсер.УстановитьСтроку(РезультатЗапроса);
 
	Пока Парсер.Прочитать() Цикл

		ЗначенияАтрибутов = Новый Соответствие();

		Если Парсер.ТипУзла = ТипУзлаXML.НачалоЭлемента И ВРег(Парсер.Имя) = "ROW" Тогда
			ЗначенияАтрибутов = ЗначенияАтрибутов(Парсер);
		Иначе
			Продолжить;
		КонецЕсли;

		Ид = ЗначенияАтрибутов["FILENAME"];
		Данные = ЗначенияАтрибутов["BINARYDATA"];

		ДанныеНеПрочитаны = (ЗначенияАтрибутов.Количество() = 0 ИЛИ Ид = Неопределено
		                 ИЛИ Данные = Неопределено ИЛИ СтрДлина(Ид) <> ДлинаИд);

		Если ДанныеНеПрочитаны Тогда
			Продолжить;
		КонецЕсли;

		Данные = Base64Значение(Данные);

		ОписаниеОбъекта = Новый Структура();
		ОписаниеОбъекта.Вставить("Ид"    , Ид);
		ОписаниеОбъекта.Вставить("Данные", Данные);

		ОбъектыКонфигурации.Вставить(ОписаниеОбъекта.Ид, ОписаниеОбъекта);

	КонецЦикла;
 
	Парсер.Закрыть();
	
	Возврат ОбъектыКонфигурации;

КонецФункции // ОбъектыКонфигурацииБазы1С()

// Функция - читает соответствия UUID объектов метаданных конфигурации 1С именам объектов базы
// из таблицы Params из записи где "[FileName] = 'DBNames'"
//
// Параметры:
//   База    - Строка    - имя базы данных
//
// Возвращаемое значение:
//    ДвоичныеДанные    - соответствия UUID объектов метаданных конфигурации 1С именам объектов СУБД
//                        упакованные в формате deflate
//
Функция ИменаТаблицОбъектовКонфигурации1С(База) Экспорт

	ТекстЗапроса = СтрШаблон("""SET NOCOUNT ON;
	                         | SELECT
	                         | [BinaryData]
	                         | FROM %1.[dbo].[Params]
	                         | WHERE [FileName] = 'DBNames'
	                         | FOR XML RAW, BINARY BASE64
	                         | SET NOCOUNT OFF;"" ",
	                         База);

	РезультатЗапроса = "";
	КодВозврата = ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса);

	Если НЕ КодВозврата = 0 Тогда
		ТекстОшибки = СтрШаблон("Ошибка получения соответствия UUID объектов метаданных конфигурации 1С
		                        | именам объектов базы ""%1\%2"":%3%4",
		                        Сервер,
		                        База,
		                        Символы.ПС,
		                        РезультатЗапроса); 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;

	НормализоватьXML(РезультатЗапроса);

	ЗначенияАтрибутов = Новый Соответствие();

	Парсер = Новый ЧтениеXML;
	Парсер.УстановитьСтроку(РезультатЗапроса);
 
	Пока Парсер.Прочитать() Цикл
		Если Парсер.ТипУзла = ТипУзлаXML.НачалоЭлемента И ВРег(Парсер.Имя) = "ROW" Тогда
			ЗначенияАтрибутов = ЗначенияАтрибутов(Парсер);
			Прервать;
		КонецЕсли;
	КонецЦикла;
 
	Парсер.Закрыть();

	Данные = ЗначенияАтрибутов["BINARYDATA"];

	Если НЕ ЗначениеЗаполнено(Данные) Тогда
		Данные = "";
	КонецЕсли;

	Возврат Base64Значение(Данные);

КонецФункции // ИменаТаблицОбъектовКонфигурации1С()

// Функция возвращает признак доступности функционала SQL Server
//
// Параметры:
//   Функционал           - Строка          - наименование проверяемого функционала
//   ОписаниеВерсии        - Соответствие    - описание версии SQL Server
//     *ИмяСервера           - Строка          - имя сервера
//     *ИмяЭкземпляраСУБД    - Строка          - имя экземпляра СУБД на сервере
//     *Редакция             - Строка          - номер редакции
//     *Версия               - Строка          - номер версии
//     *Уровень              - Строка          - уровень продукта
//     *ВерсияМакс           - Строка          - старший номер версии (2000 - 2000 (8)), 2005 - 9,
//                                                                     2008 - 10, 2012 - 11, 2014 - 12, 2016 - 13)
//     *Корп                 - Строка          - признак Enterprise версии
//
// Возвращаемое значение:
//   Булево    - Истина - функционал доступен
//
Функция ДоступностьФункционалаСУБД(Знач Функционал, ОписаниеВерсии = Неопределено) Экспорт

	МинВерсияАвторизации = 10;
	МинВерсияКомпрессии = 13;

	СтруктураФункционала = Новый Структура("Компрессия, ИзменениеАвторизации", Ложь, Ложь);

	Если НЕ ТипЗнч(ОписаниеВерсии) = Тип("Соответствие") Тогда
		ОписаниеВерсии = ПолучитьВерсиюСУБД();
	КонецЕсли;

	Если ОписаниеВерсии = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	Если ОписаниеВерсии.ВерсияМакс >= МинВерсияАвторизации Тогда
		СтруктураФункционала.ИзменениеАвторизации = Истина;
	КонецЕсли;

	Если ОписаниеВерсии.ВерсияМакс >= МинВерсияКомпрессии ИЛИ ОписаниеВерсии.Корп Тогда
		СтруктураФункционала.Компрессия = Истина;
	КонецЕсли;

	Если НЕ СтруктураФункционала.Свойство(Функционал) Тогда
		Возврат Ложь;
	КонецЕсли;

	Возврат СтруктураФункционала[Функционал];

КонецФункции // ДоступностьФункционалаСУБД()

// Функция выполняет запрос к СУБД (используется консольная утилита sqlcmd)
//
// Параметры:
//   ТекстЗапроса        - Строка    - текст исполняемого запроса
//   РезультатЗапроса    - Строка    - результат выполнения команды
//   Разделитель         - Строка    - символ - разделитель колонок результата
//   УбратьПробелы       - Булево    - Истина - будут убраны выравнивающие пробелы из результата
//
// Возвращаемое значение:
//   Булево    - Истина - команда выполнена успешно
//
Функция ВыполнитьЗапросСУБД(ТекстЗапроса, РезультатЗапроса = "", Разделитель = "", УбратьПробелы = Ложь) Экспорт

	Лог.Отладка("Текст запроса: %1", ТекстЗапроса);
	
	КодировкаВывода = КодировкаТекста.UTF8;

	НастройкаКодировки = ПолучитьПеременнуюСреды("SQLCMD_ENCODING");
	Если ЗначениеЗаполнено(НастройкаКодировки) Тогда
		Попытка
			КодировкаВывода = КодировкаТекста[НастройкаКодировки];
		Исключение
			Лог.Ошибка("В переменной среды ""SQLCMD_ENCODING"" указана некорректная
			           | кодировка ""%1"", ожидается ""UTF8"", ""OEM"", ""ANSI"".",
			           НастройкаКодировки);
		КонецПопытки;
	КонецЕсли;

	КомандаРК = Новый Команда;
	
	КомандаРК.УстановитьКоманду("sqlcmd");
	КомандаРК.УстановитьКодировкуВывода(КодировкаВывода);
	КомандаРК.ДобавитьПараметр("-S " + Сервер);
	Если ЗначениеЗаполнено(Пользователь) Тогда
		КомандаРК.ДобавитьПараметр("-U " + Пользователь);
		Если ЗначениеЗаполнено(пароль) Тогда
			КомандаРК.ДобавитьПараметр("-P " + Пароль);
		КонецЕсли;
	КонецЕсли;
	КомандаРК.ДобавитьПараметр("-Q " + ТекстЗапроса);
	КомандаРК.ДобавитьПараметр("-b");

	Если ЗначениеЗаполнено(Разделитель) Тогда
		КомандаРК.ДобавитьПараметр(СтрШаблон("-s ""%1""", Разделитель));
	КонецЕсли;

	Если УбратьПробелы Тогда
		КомандаРК.ДобавитьПараметр("-W");
	Иначе
		КомандаРК.ДобавитьПараметр("-y 0");
	КонецЕсли;

	ПутьКФайлуРезультата = ПолучитьИмяВременногоФайла();
	КомандаРК.ДобавитьПараметр(СтрШаблон("-o ""%1""", ПутьКФайлуРезультата));

	КомандаРК.УстановитьИсполнениеЧерезКомандыСистемы(Ложь);
	КомандаРК.ПоказыватьВыводНемедленно(Ложь);
	
	КодВозврата = КомандаРК.Исполнить();

	Если ФС.Существует(ПутьКФайлуРезультата) Тогда
		ТекстРезультата = Новый ТекстовыйДокумент();
		ТекстРезультата.Прочитать(ПутьКФайлуРезультата);
		РезультатЗапроса = СокрЛП(ТекстРезультата.ПолучитьТекст());
		УдалитьФайлы(ПутьКФайлуРезультата);
	Иначе
		РезультатЗапроса = КомандаРК.ПолучитьВывод();
	КонецЕсли;

	Возврат КодВозврата;

КонецФункции // ВыполнитьЗапросСУБД()

// Функция выполняет запрос к СУБД, выполняя текст из файлов скриптов (используется консольная утилита sqlcmd)
//
// Параметры:
//   МассивСкриптов      - Массив из Строка - массив с путями к файлам скриптов
//   МассивПеременных    - Массив из Строка - массив со значениями переменных вида "<Имя>=<Значение>"
//   РезультатЗапроса    - Строка - результат выполнения команды
//
// Возвращаемое значение:
//   Булево    - Истина - команда выполнена успешно
//
Функция ВыполнитьСкриптыЗапросСУБД(МассивСкриптов, МассивПеременных = Неопределено, РезультатЗапроса = "") Экспорт

	КодировкаВывода = КодировкаТекста.UTF8;

	НастройкаКодировки = ПолучитьПеременнуюСреды("SQLCMD_ENCODING");
	Если ЗначениеЗаполнено(НастройкаКодировки) Тогда
		Попытка
			КодировкаВывода = КодировкаТекста[НастройкаКодировки];
		Исключение
			Лог.Ошибка("В переменной среды ""SQLCMD_ENCODING"" указана некорректная
			           | кодировка ""%1"", ожидается ""UTF8"", ""OEM"", ""ANSI"".",
			           НастройкаКодировки);
		КонецПопытки;
	КонецЕсли;

	КомандаРК = Новый Команда;
	
	КомандаРК.УстановитьКоманду("sqlcmd");
	КомандаРК.УстановитьКодировкуВывода(КодировкаВывода);
	КомандаРК.ДобавитьПараметр("-S " + Сервер);
	Если ЗначениеЗаполнено(Пользователь) Тогда
		КомандаРК.ДобавитьПараметр("-U " + Пользователь);
		Если ЗначениеЗаполнено(пароль) Тогда
			КомандаРК.ДобавитьПараметр("-P " + Пароль);
		КонецЕсли;
	КонецЕсли;

	Для каждого Файл Из МассивСкриптов Цикл
		Лог.Отладка("Добавлен файл скрипта: %1", Файл);

		КомандаРК.ДобавитьПараметр(СтрШаблон("-i %1", Файл));		
	КонецЦикла;
	
	Если ТипЗнч(МассивПеременных) = Тип("Массив") Тогда
		Для каждого Переменная Из МассивПеременных Цикл
			Лог.Отладка("Добавлено значение переменной: %1", Переменная);
			
			КомандаРК.ДобавитьПараметр(СтрШаблон("-v %1", Переменная));		
		КонецЦикла;
	КонецЕсли;

	КомандаРК.ДобавитьПараметр("-b");

	КомандаРК.УстановитьИсполнениеЧерезКомандыСистемы( Ложь );
	КомандаРК.ПоказыватьВыводНемедленно( Ложь );
	
	КодВозврата = КомандаРК.Исполнить();

	РезультатЗапроса = КомандаРК.ПолучитьВывод();

	Возврат КодВозврата;

КонецФункции // ВыполнитьСкриптыЗапросСУБД()

// Функция преобразует текстовую строку результата запроса в структуру
//
// Параметры:
//   СтрокаРезультатаЗапроса  - Строка            - текстовая строка результат запроса
//   ПоляРезультата           - Массив из Строка  - массив имен колонок результата запроса
//   Разделитель              - Строка            - символ - разделитель колонок результата
//
// Возвращаемое значение:
//   Булево    - Истина - команда выполнена успешно
//
Функция СтрокаРезультатаЗапросаВСтруктуру(СтрокаРезультатаЗапроса, ПоляРезультата, Разделитель = "|") Экспорт

	Результат = Новый Структура();

	МассивЗначений = СтрРазделить(СтрокаРезультатаЗапроса, Разделитель);

	Для Индекс = 0 По ПоляРезультата.ВГраница() Цикл
		Ключ = СокрЛП(ПоляРезультата[Индекс]);

		Если Индекс >= МассивЗначений.Количество() Тогда
			Результат.Вставить(Ключ, Неопределено);
			Продолжить;
		КонецЕсли;

		Результат.Вставить(Ключ, СокрЛП(МассивЗначений[Индекс]));
	КонецЦикла;

	Возврат Результат;

КонецФункции // СтрокаРезультатаЗапросаВСтруктуру()

#КонецОбласти // ПрограммныйИнтерфейс

#Область СлужебныеПроцедурыИФункции

// Функция возвращает список полей таблицы информации о резервной копии
//
// Возвращаемое значение:
//   Строка    - список полей таблицы с информацией о резервной копии (разделенный ",")
//
Функция ПоляТаблицыФайловРезервнойКопии()

	ОписаниеПолей = "[LogicalName] nvarchar(128),
	                |[PhysicalName] nvarchar(260),
	                |[Type] char(1),
	                |[FileGroupName] nvarchar(128),
	                |[Size] numeric(20,0),
	                |[MaxSize] numeric(20,0),
	                |[FileID] bigint,
	                |[CreateLSN] numeric(25,0),
	                |[DropLSN] numeric(25,0) NULL,
	                |[UniqueID] uniqueidentifier,
	                |[ReadOnlyLSN] numeric(25,0) NULL,
	                |[ReadWriteLSN] numeric(25,0) NULL,
	                |[BackupSizeInBytes] bigint,
	                |[SourceBlockSize] int,
	                |[FileGroupID] int,
	                |[LogGroupGUID] uniqueidentifier NULL,
	                |[DifferentialBaseLSN] numeric(25,0) NULL,
	                |[DifferentialBaseGUID] uniqueidentifier,
	                |[IsReadOnly] bit,
	                |[IsPresent] bit,
	                |[TDEThumbprint] varbinary(32)";

	ОписаниеВерсии = ПолучитьВерсиюСУБД();
	
	Версия2016 = 13;

	Если ОписаниеВерсии.ВерсияМакс >= Версия2016 Тогда
		ОписаниеПолей = СтрШаблон("%1,
		                          |[SnapshotUrl] nvarchar(360)",
		                          ОписаниеПолей);
	КонецЕсли;
	
	Возврат ОписаниеПолей;

КонецФункции // ПоляТаблицыФайловРезервнойКопии()

// Функция возвращает список возможных типов файлов базы данных или таблиц резервной копии
//
// Параметры:
//   Сокращенные    - Булево    - Истина - возвращать список сокращенных обозначений
//                                         типов баз (для файлов в файлах резервных копий);
//                                Ложь - список полных обозначений (для файлов баз данных)
//
// Возвращаемое значение:
//   ФиксированнаяСтруктура    - список возможных типов файлов базы данных или таблиц резервной копии
//
Функция ТипыФайловБД(Сокращенные = Ложь)

	ТипыФайлов = Новый Структура();
	ТипыФайлов.Вставить("Данные"    , "ROWS");
	ТипыФайлов.Вставить("Журнал"    , "LOG");

	ТипыФайловСокр = Новый Структура();
	ТипыФайловСокр.Вставить("Данные", "D");
	ТипыФайловСокр.Вставить("Журнал", "L");

	Возврат Новый ФиксированнаяСтруктура(?(Сокращенные, ТипыФайловСокр, ТипыФайлов));

КонецФункции // ТипыФайловБД()

// Функция возвращает список вариантов сообщения о существовании базы данных при проверке
//
// Возвращаемое значение:
//   ФиксированнаяСтруктура    - варианты сообщения о существовании базы данных при проверке
//
Функция ВариантыСообщенияОСуществованииБД()

	ВариантыСообщения = Новый Структура();
	ВариантыСообщения.Вставить("НеСообщать"                , "НЕСООБЩАТЬ");
	ВариантыСообщения.Вставить("СообщатьОСуществовании"    , "СООБЩАТЬОСУЩЕСТВОВАНИИ");
	ВариантыСообщения.Вставить("ИсключениеПриСуществовании", "ИСКЛЮЧЕНИЕПРИСУЩЕСТВОВАНИИ");
	ВариантыСообщения.Вставить("СообщатьОбОтсутствии"      , "СООБЩАТЬОБОТСУТСТВИИ");
	ВариантыСообщения.Вставить("ИсключениеПриОтсутствии"   , "ИСКЛЮЧЕНИЕПРИОТСУТСТВИИ");

	Возврат Новый ФиксированнаяСтруктура(ВариантыСообщения);

КонецФункции // ВариантыСообщенияОСуществованииБД()

// Функция возвращает список возможных моделей восстановления базы данных
//
// Возвращаемое значение:
//    ФиксированнаяСтруктура    - возможные модели восстановления базы данных
//
Функция МоделиВосстановленияБД()

	МоделиВосстановления = Новый Структура();
	МоделиВосстановления.Вставить("Простая"                    , "SIMPLE");
	МоделиВосстановления.Вставить("Полная"                     , "FULL");
	МоделиВосстановления.Вставить("МинимальноеПротоколирование", "BULK_LOGGED");

	Возврат Новый ФиксированнаяСтруктура(МоделиВосстановления);

КонецФункции // ВариантыСообщенияОСуществованииБД()

// Функция - читает атрибуты узла XML
//
// Параметры:
//   Парсер    - ЧтениеXML    - парсер, спозиционированный на начало элемента XML
//
// Возвращаемое значение:
//    Соответствие    - прочитанные значения атрибутов узла XML
//
Функция ЗначенияАтрибутов(Парсер)

	Результат = Новый Соответствие();

	КоличествоАтрибутов = Парсер.КоличествоАтрибутов();

	Для й = 0 По КоличествоАтрибутов -1 Цикл
		Результат.Вставить(ВРег(Парсер.ИмяАтрибута(й)), Парсер.ЗначениеАтрибута(й));
	КонецЦикла;

	Возврат Результат;

КонецФункции // ЗначенияАтрибутов()

// Процедура - добавляет стандартный заголовок XML и корневой элемент
//
// Параметры:
//  ТекстXML     - Строка    - дополняемый техт XML
// 
Процедура НормализоватьXML(ТекстXML)

	ТекстXML = СтрЗаменить(ТекстXML, Символы.ПС, "");
	ТекстXML = СтрЗаменить(ТекстXML, Символы.ВК, "");

	Текст = Новый ТекстовыйДокумент();
	Текст.УстановитьТекст(ТекстXML);
	Текст.ВставитьСтроку(1, "<data>");
	Текст.ВставитьСтроку(1, "<?xml version=""1.0"" encoding=""utf-8""?>");
	Текст.ДобавитьСтроку("</data>");

	ТекстXML = Текст.ПолучитьТекст();

КонецПроцедуры // НормализоватьXML()

// ФункцияПроцедура - добавляет стандартный заголовок XML и корневой элемент
//
// Параметры:
//  ДатаСтрокой     - Строка    - дата и время строкой
//
// Возвращаемое значение:
//  Дата    - преобразованная дата
// 
Функция ДатаИзСтроки(ДатаСтрокой)

	ДатаИВремя = СтрРазделить(ДатаСтрокой, " ", Ложь);

	ВремЧастиДаты = СтрРазделить(ДатаИВремя[0], "-", Ложь);
	ВремЧастиВремени = СтрРазделить(ДатаИВремя[1], ".", Ложь);
	ВремЧастиВремени = СтрРазделить(ВремЧастиВремени[0], ":", Ложь);

	Результат = Дата(Число(ВремЧастиДаты[0]),
	                 Число(ВремЧастиДаты[1]),
	                 Число(ВремЧастиДаты[2]),
	                 Число(ВремЧастиВремени[0]),
	                 Число(ВремЧастиВремени[1]),
	                 Число(ВремЧастиВремени[2]));

	Возврат Результат;

КонецФункции // ДатаИзСтроки()

// Функция - возвращает части запроса SQL для отбора данных из таблицы Config
// по списку идентификаторов (FileName)
//
// Параметры:
//   ИдОбъектов    - Число     - массив идентификаторов объектов метаданных,
//                               если не указан, считываются все записи
//
// Возвращаемое значение:
//   Число    - количество записей в таблице конфигурации информационной базы 1С
//
Функция ОтборОбъектовКонфигурации1СПоИд(ИдОбъектов = "")

	МассивИд = Новый Массив();
	Если ТипЗнч(ИдОбъектов) = Тип("Строка") Тогда
		МассивИд = СтрРазделить(ИдОбъектов, ",", Ложь);
	Иначе
		Для Каждого ТекИд Из ИдОбъектов Цикл
			МассивИд.Добавить(ТекИд);
		КонецЦикла;
	КонецЕсли;

	ТаблицаОтбора = "";
	Отбор = "";
	Если МассивИд.Количество() > 0 Тогда
		Для й = 0 По МассивИд.ВГраница() Цикл
			МассивИд[й] = СтрШаблон("('%1')", СокрЛП(МассивИд[й]));
		КонецЦикла;

		ЗначенияИд = СтрСоединить(МассивИд, ",");

		ТаблицаОтбора = СтрШаблон("DECLARE @IDFilter TABLE (FileName NVARCHAR(128))
		                          | INSERT INTO @IDFilter ([FileName]) VALUES %1", ЗначенияИд);
		Отбор = " INNER JOIN @IDFilter AS IDFilter
		        | ON Config.[FileName] = IDFilter.[FileName]";
	КонецЕсли;

	Возврат Новый Структура("ТаблицаОтбора, Отбор", ТаблицаОтбора, Отбор);

КонецФункции // ОтборОбъектовКонфигурации1СПоИд()

#КонецОбласти // СлужебныеПроцедурыИФункции

#Область ОбработчикиСобытий

// Процедура - обработчик события "ПриСозданииОбъекта"
//
// Параметры:
//   _Сервер          - Строка    - адрес сервера СУБД
//   _Пользователь    - Строка    - пользователь сервера СУБД
//   _Пароль          - Строка    - пароль пользователя сервера СУБД
//
Процедура ПриСозданииОбъекта(Знач _Сервер, Знач _Пользователь, Знач _Пароль) Экспорт
	
	Сервер       = _Сервер;
	Пользователь = _Пользователь;
	Пароль       = _Пароль;
	
	Лог = ПараметрыСистемы.Лог();

КонецПроцедуры // ПриСозданииОбъекта()

#КонецОбласти // ОбработчикиСобытий
